package com.touzhijia.authority.job;

import com.touzhijia.authority.domain.entity.User;
import com.touzhijia.authority.mapper.UserMapper;
import com.touzhijia.authority.model.LdapUser;
import com.touzhijia.authority.repository.LdapUserRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 作者： lzw<br/>
 * 创建时间：2018-03-14 14:28 <br/>
 */
@Service
@Slf4j
public class SyncLdapUserJob {

    @Autowired
    private LdapUserRepository ldapUserRepository;

    @Autowired
    private UserMapper userMapper;

    /**
     * 同步LDAP用户信息
     */
    @Scheduled(cron = "0 0/5 * * * ?")
    public synchronized void syncLdapUser() {
        log.info("### [同步LDAP用户信息] 开始");
        int count = 1;
        final Date now = new Date();
        Iterable<LdapUser> ldapUserList = ldapUserRepository.findAll();
        for (LdapUser ldapUser : ldapUserList) {
            try {
                log.info("### [同步LDAP用户信息] 计数[{}] 同步用户[{}]", (count++), ldapUser.getUsername());
                addUser(ldapUser, now);
            } catch (Throwable e) {
                log.error("### [同步LDAP用户信息] 同步用户失败", e);
            }
        }
        // 处理已从LDAP上移除的用户
        List<User> userList = userMapper.findOnLdapRemoveUser(now);
        for (User user : userList) {
            boolean flag = true;
            for (LdapUser ldapUser : ldapUserList) {
                if (Objects.equals(ldapUser.getUsername(), user.getUsername())) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                try {
                    log.info("### [同步LDAP用户信息] 计数[{}] 移除用户[{}]", (count++), user.getUsername());
                    onLdapRemoveUser(user, now);
                } catch (Throwable e) {
                    log.error("### [同步LDAP用户信息] 处理已从LDAP上移除的用户失败", e);
                }
            }
        }
        log.info("### [同步LDAP用户信息] 完成");
    }

    /**
     * 新增或者更新用户信息
     */
    @Transactional
    protected synchronized void addUser(LdapUser ldapUser, Date now) {
        User user = userMapper.getByUsername(ldapUser.getUsername());
        if (user != null) {
            // 用户存在 更新同步信息
            if (Objects.equals(user.getUserType(), User.User_Type_1)) {
                User update = new User();
                update.setId(user.getId());
                update.setNickname(ldapUser.getNickname());
                update.setTelephone(ldapUser.getTelephone());
                update.setEmail(ldapUser.getEmail());

                update.setMemberOf(getMemberOf(ldapUser.getMemberOf()));
                update.setUserType(User.User_Type_1);
                update.setLdapExist(User.Ldap_Exist_1);
                update.setUpdateAt(now);
                userMapper.updateByPrimaryKeySelective(update);
                log.info("### [同步LDAP用户信息] 更新用户成功");
            } else {
                log.info("### [同步LDAP用户信息] 当前用户已经手动创建了，无法同步");
            }
            return;
        }
        user = new User();
        user.setUsername(ldapUser.getUsername());
        user.setPassword(null);
        user.setNickname(ldapUser.getNickname());
        user.setTelephone(ldapUser.getTelephone());
        user.setEmail(ldapUser.getEmail());
        user.setMemberOf(getMemberOf(ldapUser.getMemberOf()));
        user.setUserType(User.User_Type_1);
        user.setLdapExist(User.Ldap_Exist_1);
        user.setLocked(User.Locked_0);
        user.setEnabled(User.Enabled_1);
        user.setDescription("自动从LDAP服务同步的用户");
        user.setCreateAt(new Date());
        user.setUpdateAt(null);
        userMapper.insert(user);
        log.info("### [同步LDAP用户信息] 新增用户成功");
    }

    private String getMemberOf(String memberOf) {
        if (StringUtils.isBlank(memberOf)) {
            return memberOf;
        }
        String[] array = memberOf.split(",");
        for (String str : array) {
            if (StringUtils.isBlank(str)) {
                continue;
            }
            if (str.indexOf('=') >= 0) {
                return str.substring(str.indexOf('=') + 1);
            }
        }
        return memberOf;
    }

    /**
     * 从LDAP服务器同步过来的用户当被LDAP移除时的处理
     */
    @Transactional
    protected synchronized void onLdapRemoveUser(User user, Date now) {
        if (!Objects.equals(user.getUserType(), User.User_Type_1)) {
            return;
        }
        User update = new User();
        update.setId(user.getId());
        update.setLdapExist(User.Ldap_Exist_0);
        update.setUpdateAt(now);
        userMapper.updateByPrimaryKeySelective(update);
        // TODO Spring Security 处理
        log.info("### [同步LDAP用户信息] 移除用户成功");
    }
}
